#include "zoomlabel.h"
#include "commonFunc.h"

ZoomLabel::ZoomLabel()
{
    //setScaledContents(true);
    setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    setMouseTracking(true);
    isCompleteEdit = false;
    tmp = new std::map<QString,Point*>();
    pic = new QImage();
    pmap = new QPixmap();
    currImg = new QImage();
    regionTmp = new std::map<QString,Point*>();
    rotateFactor = 0.0;
}
void ZoomLabel::scaleImage(QPixmap &p,double scaleFactor,bool inner)
{
    //if(((double)(p.size() * scaleFactor).width()) / (double)origPicSize.width() >= 1.0)
    //if(((double)(p.size() * scaleFactor).width()) / (double)currImg.size().width() >= 1.0)
    if(getStatus() != 0 && inner == false) return;

    QPixmap scaledPic;
    scaledPic.fill(Qt::white);
    QImage scalImg;
    //scalImg.fill(Qt::white);
    //scalImg = p.toImage();
    scalImg = *currImg;
    scalImg = scalImg.scaled(origPicSize * scaleFactor, Qt::AspectRatioMode::IgnoreAspectRatio);
    centerPos = QPoint(origPicSize.width() * scaleFactor / qreal(2) ,origPicSize.height() * scaleFactor / qreal(2));
    scaledPic = QPixmap::fromImage(scalImg);
    /*
    if(rotateFactor != 0)
    {
      scalImg = rotateImage(&scalImg,centerPos,rotateFactor,imgOffset);
    }
   */
    setPixmap(scaledPic);
}
QImage ZoomLabel::rotateImage(QImage *img,QPoint center,double rotateAng,QPoint imgOffset)
{
    return rotateImg(img,center,rotateAng,imgOffset);
}
void ZoomLabel::wheelEvent(QWheelEvent *event)
{
    //scaleFactor = 1.0;
    if (event->angleDelta().y() > 0) { //Zoom in
        scaleFactor *= scaleStep;
    } else { // Zoom out
        scaleFactor /= scaleStep;
    }
    scaleFactor = qBound(0.1, scaleFactor, 10.0);
    scaleImage(*pmap,scaleFactor,true);
}
void ZoomLabel::setScaleFactor(double factor)
{
    scaleFactor = factor;
}
 void ZoomLabel::setRotateFactor(double factor)
 {
     rotateFactor = factor;
 }
QPoint ZoomLabel::getCenterPos(){
    return centerPos;
}
void ZoomLabel::setCenterPos(QPoint pos)
{
    centerPos = pos;
}
void ZoomLabel::setPixmap(const QPixmap &p)
{
    *pic = p.toImage();
    *pmap = p;
    realPicSize = p.size();
    update();
}
void ZoomLabel::setPixel(int x,int y,uint rgb)
{
    QImage img = (*pmap).toImage();
    img.setPixel(x,y,rgb);
    QPixmap result = QPixmap::fromImage(img);
    setPixmap(result);
}
void ZoomLabel::paintEvent(QPaintEvent *event)
{
     //QPixmap *tmpPix = new QPixmap();
     //*tmpPix = *pmap;
     QLabel::paintEvent(event);
     QPainter painter;
     painter.begin(this);
     QPoint rotateCenter = centerPos + imgOffset;
     double rAng = 360 - rotateFactor;
     QMatrix transform;
     transform = transform.translate(rotateCenter.x(),rotateCenter.y()).rotate(rAng).translate(-(rotateCenter.x()),-(rotateCenter.y()));
     if(!pmap->size().isEmpty())
     {
         if(rotateFactor != 0)
         {
             painter.translate(centerPos + imgOffset);
             painter.rotate(rotateFactor);
             painter.translate(-(centerPos + imgOffset));
             painter.drawImage(imgOffset,pmap->toImage());
         }
         else
         {
             painter.drawImage(imgOffset,pmap->toImage());
         }

     }
     //画点
     if(!tempPt.empty() && getMode() == 1)
     {
         painter.setPen(QPen(Qt::green,5));
         //painter.setPen(QPen(Qt::green,10));
         std::vector<QPoint*> temp;
         if(rotateFactor != 0)
         {
             for(auto i = tempPt.begin();i!=tempPt.end();i++)
             {

                 QPoint pt = (*((*i).first) * scaleFactor) + imgOffset;
                 pt = transform.map(pt);
                 painter.drawPoint(pt);
             }
         }
         else
         {
             for(auto i = tempPt.begin();i!=tempPt.end();i++)
             {
                 QPoint pt = (*((*i).first) * scaleFactor) + imgOffset;
                 painter.drawPoint(pt);
                 //painter.drawPoint(**i);
             }
         }

     }
    //画出多边形选区
     if(isCompleteEdit && !poly.empty())
     {
         polyOffset = QPoint(getPicOffset());
         painter.drawPolygon(poly);
         painter.eraseRect(this->rect());
         painter.setPen(QPen(Qt::green,5));

         QImage srcImg = pmap->toImage();
         QImage dstImg = Crop(pmap->toImage(),poly);

         *pmap = QPixmap::fromImage(dstImg);
         *pic = dstImg;
         double scaleRatio = (double) this->width() / (double) poly.boundingRect().width();
         double scaleRatio1 = (double) this->height() / (double) poly.boundingRect().height();
         double outputRate = (double) origPicSize.width() / (double) realPicSize.width();
         //QPixmap scaledPixmap = pmap->scaled(pmap->size().width() * scaleRatio,pmap->size().height() * scaleRatio1,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
         //*pmap = scaledPixmap;
         //*pic = scaledPixmap.toImage();
         *currImg = pmap->toImage();
         imgOffset.setX(0);
         imgOffset.setY(0);
         transform = transform.translate(rotateCenter.x(),rotateCenter.y()).rotate(0).translate(-(rotateCenter.x()),-(rotateCenter.y()));

         painter.translate(centerPos + imgOffset);
         painter.rotate(rAng);
         painter.translate(-(centerPos + imgOffset));

         painter.drawImage(imgOffset,*pic);
         rotateFactor = 0;

         realPicSize = pmap->size();
         realPicSize = realPicSize * scaleRatio;
         /*
         for(int y=0;y < poly.boundingRect().height() * scaleRatio1;y++)
         {
             for(int x = 0;x<poly.boundingRect().width() * scaleRatio;x++)
             {
                    int x1= (x/scaleRatio) + poly.boundingRect().left();
                    int y1 = (y/scaleRatio1) + poly.boundingRect().top();
                    QPoint pt(x1,y1);

                    QPoint pos = (pt- polyOffset) * outputRate ;
                    QString pos1 = QString::number(pos.rx()) + "," + QString::number(pos.ry());

                    QString pos2 = QString::number(x) + "," + QString::number(y);
                    if(tmp->find(pos1)!=tmp->end())
                    {
                        regionTmp->insert(std::make_pair(pos2,(*tmp)[pos1]));
                    }
             }
         }
         */
         isCompleteEdit = false;
     }

     painter.end();
}
void ZoomLabel::mousePressEvent(QMouseEvent *event)
{
    //offset = event->pos() - QPoint(pic->rect().x(),pic->rect().y());
    //offset = QPoint(pic->rect().x(),pic->rect().y());
    offset = imgOffset;
    currMousePos = event->pos();
    lastPoint = event->pos();
    if(event->button() == Qt::LeftButton)
    {
        if(getMode() == 1)
        {
            //QString inputStr = QInputDialog::getText(this,"点名称","请输入名称");
            //tempPt.push_back(new QPoint(event->pos()));
            //if(inputStr.length() > 0)
                //tempPt.insert(std::make_pair(new QPoint((event->pos() - imgOffset) / scaleFactor),inputStr));
            NamingDialog nameDialog;
            if(nameDialog.exec() == QDialog::Accepted)
            {
                QString x = nameDialog.getX();
                QString y = nameDialog.getX();
                if(x.length() > 0 && y.length() > 0)
                {
                    QString concatStr = x + " " + y;
                    tempPt.insert(std::make_pair(new QPoint((event->pos() - imgOffset) / scaleFactor),concatStr));
                }

            }
            update();
        }
        emit clicked();
    }
    else if(event->button() == Qt::RightButton)
    {
        isDragging = true;
        //旋转状态
        if(getStatus() == 1)
        {
            isRotating = true;
            //获取图片中心
            lastRotatePoint = event->pos();
            rotateAng = rotateFactor;
            isDragging = false;
        }
    }
     event->accept();
}
void ZoomLabel::mouseMoveEvent(QMouseEvent *event)
{
    if (isDragging && event->buttons() == Qt::RightButton) {
        QPoint data1 = (event->pos() - currMousePos) + offset;
        imgOffset = data1;
        //imgOffset.rx() = qBound(-1 * width(), imgOffset.x(), width());
        //imgOffset.ry() = qBound(-1 * height(), imgOffset.y(), height());
        update();
        //now = event->pos();
        event->accept();
    }
    if(isRotating && getStatus() == 1 && event->buttons() == Qt::RightButton)
    {
        QPoint currPt = event->pos();
        QPoint center = imgOffset + centerPos;
        //QPoint vec1 = currPt - center;
        //QPoint vec2 = lastRotatePoint - center;
        QLineF v1(center,currPt);
        QLineF v2(center,lastRotatePoint);
        double angle = v1.angleTo(v2);
        rotateAng += angle;
        /*
        double d = QPoint::dotProduct(vec1,vec2);
        double lengthV1 = sqrt((vec1.x() * vec1.x()) + (vec1.y() * vec1.y()));
        double lengthV2 = sqrt((vec2.x() * vec2.x()) + (vec2.y() * vec2.y()));
        double ang = std::acos(d /(lengthV1 * lengthV2)) * 180 / pi;
        if(getStatus() == 1)
        {
            rotateAng += ang;
            rotateImage(abs(rotateAng));
        }
        else if(getStatus() == 2)
        {
            rotateAng += -1 * ang;
            rotateImage(rotateAng);
        }
        lastRotatePoint = event->pos();
        */
        if(rotateAng > 360) rotateAng = fmod(rotateAng,360.0);
        rotateFactor = rotateAng;
        //scaleImage(*pmap,scaleFactor,true);
        lastRotatePoint = event->pos();
        update();
        event->accept();
    }
}
void ZoomLabel::mouseReleaseEvent(QMouseEvent *event)
{
     if (event->button() == Qt::RightButton && isDragging) {
         isDragging = false;
         event->accept();
         offset.setX(0);
         offset.setY(0);
     }
     else
     {
         if(getStatus() != 0 && event->button() == Qt::RightButton)
         {
             isRotating = false;
             rotateFactor = rotateAng;
             event->accept();
         }
     }

}
void ZoomLabel::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_Right || event->key() == Qt::Key_Left)
    {
        if(status == 1)
        {
            switch(event->key())
            {
            case Qt::Key_Left:
                rotateFactor += 1;
                update();
                break;
            case Qt::Key_Right:
                rotateFactor -= 1;
                update();
                break;
            default:
                keyPressEvent(event);
            }
        }
    }
}
void ZoomLabel::setTemp(std::map<QString,Point*> t)
{
    tmp->clear();
    regionTmp->clear();
    *tmp = t;
}
std::map<QString,Point*> ZoomLabel::getTemp()
{
    return *tmp;
}
QPoint ZoomLabel::getMousePos()
{
    return currMousePos;
}
double ZoomLabel::getScaleFactor()
{
    return scaleFactor;
}
void ZoomLabel::setOrigPicSize(QSize picSize)
{
    if(!picSize.isEmpty())
    {
        origPicSize = picSize;
    }
}
QSize ZoomLabel::getOrigPicSize()
{
    return origPicSize;
}
QPoint ZoomLabel::getPicOffset()
{
    return imgOffset;
}
double ZoomLabel::getRotateFactor()
{
    return rotateFactor;
}
QSize ZoomLabel::getRealPicSize()
{
    return realPicSize;
}
void ZoomLabel::setMode(int mode)
{
    if(this->mode == 1 && mode == 0)
    {
        isCompleteEdit = true;
    }
    else if (this->mode == 0)
    {
        isCompleteEdit = false;
        tempPt.clear();
        //regionTmp->clear();
        //poly.clear();
    }
    this->mode = mode;

}
int ZoomLabel::getMode()
{
    return this->mode;
}
 int ZoomLabel::getStatus()
 {
     return this->status;
 }
void ZoomLabel::setStatus(int status)
{
    this->status = status;
}
void ZoomLabel::reRender()
{

}
 void ZoomLabel::refresh()
 {
    update();
 }
 QImage ZoomLabel::Crop(QImage srcImg,QPolygon sect)
 {
        QImage resImg(srcImg.size(),QImage::Format_ARGB32);
        QMatrix transform;
        //QPoint centers(sect.boundingRect().x() + imgOffset.x(),sect.boundingRect().y() + imgOffset.y());
        QPoint centers = centerPos + imgOffset;
        transform = transform.translate(centers.x(),centers.y()).rotate(rotateFactor).translate(-(centers.x()),-(centers.y()));

        //resultImg.fill(Qt::white);
        double rateX = (double)srcImg.width() / (double)sect.boundingRect().width();
        double rateY = (double) srcImg.height() / (double)sect.boundingRect().height();
        //QPainter resultPainter(&resultImg);

        QPainter resultPainter(&resImg);


        int PtsCnt[sect.boundingRect().bottom() - sect.boundingRect().y() + 1];
        QPoint Pts[sect.boundingRect().bottom() - sect.boundingRect().y() + 1];
        int tmpPt = 0;
        bool pcount = true;
        for (int y = sect.boundingRect().y(); y <= sect.boundingRect().bottom(); y++) {
            tmpPt = 0;
            pcount = true;
            for (int x = sect.boundingRect().x(); x <= sect.boundingRect().right(); x++) {
                QPoint pt(x,y);
                if (sect.containsPoint(pt, Qt::WindingFill)) {
                    ++tmpPt;
                    if(pcount)
                    {
                        Pts[y - sect.boundingRect().y()] = QPoint(x - sect.boundingRect().x(),y - sect.boundingRect().y());
                        pcount = false;
                    }
                }
            }
            PtsCnt[y - sect.boundingRect().y()] = tmpPt;
            //qDebug()  << y - sect.boundingRect().y() << ",xvalue:" << Pts[y - sect.boundingRect().y()]  << ",ptsCount:" << PtsCnt[y - sect.boundingRect().y()];
        }
        //rateX = (double)srcImg.width() / (double)ratePt;
        /*
         for (int y = sect.boundingRect().y(); y < sect.boundingRect().bottom(); ++y) {
                for (int x = sect.boundingRect().x(); x < sect.boundingRect().right(); ++x) {
                    QPoint pt(x,y);
                    if (sect.containsPoint(pt, Qt::WindingFill)) {
                        // 获取源图像中对应位置的像素
                        pt = pt - imgOffset;
                        QColor pixelColor = srcImg.pixelColor(pt.rx(), pt.ry());
                        // 设置结果图像中对应位置的像素
                        resultImg.setPixel(x - sect.boundingRect().x(), y - sect.boundingRect().y(), pixelColor.rgb());
                        //resultImg.setPixel(x * rateX,y * rateY, pixelColor.rgb());
                    }
                    else
                    {
                        //resultImg.setPixel(x * rateX,y * rateY, Qt::white);
                        resultImg.setPixel(x - sect.boundingRect().x(), y - sect.boundingRect().y(), Qt::white);
                    }
                }
         }
*/
        //return resultImg;
        if(rateY < 1) rateY = 1;
        for(int j =0;j < resImg.size().height();j++)
        {
            int resY = ((double)j / (double)rateY);
            if(resY <= 0) resY = 0;
            if(resY > sect.boundingRect().bottom() - sect.boundingRect().y()) resY = sect.boundingRect().bottom() - sect.boundingRect().y() ;
            //rateX = std::floor((double)resImg.size().width() / (double)PtsCnt[jjj]);
            rateX = (double)resImg.size().width() / (double)PtsCnt[resY];
            for(int i=0;i < resImg.size().width();i++)
            {
                int resX = ((double)i / rateX) + Pts[resY].x();

               //qDebug()  <<"sect_h:" << sect.boundingRect().height() << ",sect_w:" << sect.boundingRect().width()<< ",i:" <<i   << ",j:" << j << ",rateX:" << rateX << "rateY:" << rateY<<",width:" << resImg.size().width()<<",height:" << resImg.size().height()  << ",count:" << PtsCnt[resY] << ",resX:" << resX  << ",resY" << resY<< ",pt:" << Pts[resY];
                QPoint pt(resX,resY);
                //pt = pt + imgOffset;
                {
                    QColor pixelColor = srcImg.pixelColor(pt.rx() + sect.boundingRect().x(), pt.ry() + sect.boundingRect().y());
                    //QPoint rotatedPt = transform.map(QPoint(i,j) + imgOffset);
                    resImg.setPixel(i,j,pixelColor.rgb());
                    //rotatedPt -= imgOffset;
                    //resImg.setPixel(rotatedPt.x(),rotatedPt.y(),pixelColor.rgb());

                    QPoint pos(pt.rx() + sect.boundingRect().x(),pt.ry() + sect.boundingRect().y());
                    QPoint pos1 = ((pos- imgOffset) / scaleFactor) ;
                    QString pos12 = QString::number(i) + "," + QString::number(j);
                    //QString pos12 = QString::number(rotatedPt.x()) + "," + QString::number(rotatedPt.y());
                    QString pos2 = QString::number(pos1.x()) + "," + QString::number(pos1.y());
                    if(tmp->find(pos2)!=tmp->end())
                    {
                        regionTmp->insert(std::make_pair(pos12,(*tmp)[pos2]));
                    }
                }
            }
        }
        return resImg;
 }
 bool ZoomLabel::getEditStatus()
 {
     return isCompleteEdit;
 }
 QPoint ZoomLabel::getPolyOffset()
 {
    return polyOffset;
 }
 QImage ZoomLabel::getPic()
 {
     return *pic;
 }
 QPixmap ZoomLabel::getPmap()
 {
     return *pmap;
 }
 void ZoomLabel::setPic(QImage img)
 {
     *pic = img;
 }
 void ZoomLabel::setPmap(QPixmap map)
 {
     pmap = &map;
 }
 void ZoomLabel::setEditStatus(bool status)
 {
     isCompleteEdit = status;
 }
 void ZoomLabel::setPicOffset(QPoint off)
 {
     imgOffset = off;
 }
 void ZoomLabel::setPolyOffset(QPoint off)
 {
     polyOffset = off;
 }
void ZoomLabel::setRealPicSize(QSize s)
{
    realPicSize = s;
}
